<template>
    <div class="tags-nav">
        <div class="close-con">
            <Dropdown transfer @on-click="handleTagsOption" style="margin-top:7px;">
                <Button size="small" type="text">
                    <Icon :size="18" type="ios-close-circle-outline" />
                </Button>
                <DropdownMenu slot="list">
                    <DropdownItem name="close-all">关闭所有</DropdownItem>
                    <DropdownItem name="close-others">关闭其他</DropdownItem>
                </DropdownMenu>
            </Dropdown>
        </div>
        <ul v-show="visible" :style="{left: contextMenuLeft + 'px', top: contextMenuTop + 'px'}" class="contextmenu">
            <li v-for="(item, key) of menuList" @click="handleTagsOption(key)" :key="key">{{item}}</li>
        </ul>
        <div class="btn-con left-btn">
            <Button type="text" @click="handleScroll(240)">
                <Icon :size="18" type="ios-arrow-back" />
            </Button>
        </div>
        <div class="btn-con right-btn">
            <Button type="text" @click="handleScroll(-240)">
                <Icon :size="18" type="ios-arrow-forward" />
            </Button>
        </div>
        <div class="scroll-outer" ref="scrollOuter" @DOMMouseScroll="handlescroll" @mousewheel="handlescroll">
            <div ref="scrollBody" class="scroll-body" :style="{left: tagBodyLeft + 'px'}">
                <transition-group name="taglist-moving-animation">
                    <Tag type="dot" v-for="(item, index) in tagList" ref="tagsPageOpened" :key="`tag-nav-${index}`" :name="item.name"
                        :data-route-item="item"
                        @on-close="handleClose(item)"
                        @click.native="handleClick(item)"
                        :closable="item.name !== $config.homeName"
                        :color="isCurrentTag(item) ? 'primary' : 'default'"
                        @contextmenu.prevent.native="contextMenu(item, $event)"

                        :draggable="index != 0"
                        @dragstart.native="handleDragStart(index)"
                        @dragover.prevent.native="handleDragOver(index)"
                        @dragend.native="handleDragEnd"
                        @drop.prevent.native="handleDrop(index)">
                        {{ showTitleInside(item) }}
                    </Tag>
                </transition-group>
            </div>
        </div>
    </div>
</template>

<script>
import { showTitle, routeEqual } from '@/libs/util'
import beforeClose from '@/router/before-close'
export default {
    name: 'TagsNav',
    props: {
        value: Object,
        list: {
            type: Array,
            default () {
                return []
            }
        }
    },
    data () {
        return {
            tagList: [...this.list],
            tagBodyLeft: 0,
            rightOffset: 40,
            outerPadding: 4,
            contextMenuLeft: 0,
            contextMenuTop: 0,
            visible: false,
            menuList: {
                others: '关闭其他',
                all: '关闭所有'
            },

            /*拖拽*/
            draggingIndex: null,
            dropIndex: null,
        }
    },
    watch: {
        '$route' (to) {
            this.getTagElementByName(to)
        },
        visible (value) {
            if (value) {
                document.body.addEventListener('click', this.closeMenu)
            } else {
                document.body.removeEventListener('click', this.closeMenu)
            }
        },
        list(newVal) {
            this.tagList = [...newVal];
        }
    },
    computed: {
        currentRouteObj () {
            let { name, params, query } = this.value
            return { name, params, query }
        }
    },
    methods: {
        // 记录开始拖拽的元素索引
        handleDragStart(index) {
            this.draggingIndex = index;
        },
        // 记录当前拖拽经过的元素索引
        handleDragOver(index) {
            this.dropIndex = index;
        },
        // 拖拽结束，重置状态
        handleDragEnd() {
            this.draggingIndex = null;
            this.dropIndex = null;
        },
        handleDrop(index) {
            // 当拖拽源和目标不同时才执行排序
            if (this.draggingIndex !== index && index !== 0) {
                // 复制原数组
                const newList = [...this.tagList];
                // 移除拖拽的元素
                const [removedItem] = newList.splice(this.draggingIndex, 1);
                // 将移除的元素插入到新位置
                newList.splice(index, 0, removedItem);
                // 更新数据
                this.tagList = newList;
                this.$emit('on-draw', this.tagList);
            }
            // 重置状态
            this.handleDragEnd();
        },

        handlescroll (e) {
            var type = e.type
            let delta = 0
            if (type === 'DOMMouseScroll' || type === 'mousewheel') {
                delta = (e.wheelDelta) ? e.wheelDelta : -(e.detail || 0) * 40
            }
            this.handleScroll(delta)
        },
        handleScroll (offset) {
            const outerWidth = this.$refs.scrollOuter.offsetWidth
            const bodyWidth = this.$refs.scrollBody.offsetWidth
            if (offset > 0) {
                this.tagBodyLeft = Math.min(0, this.tagBodyLeft + offset)
            } else {
                if (outerWidth < bodyWidth) {
                    if (this.tagBodyLeft < -(bodyWidth - outerWidth)) {
                        this.tagBodyLeft = this.tagBodyLeft
                    } else {
                        this.tagBodyLeft = Math.max(this.tagBodyLeft + offset, outerWidth - bodyWidth)
                    }
                } else {
                    this.tagBodyLeft = 0
                }
            }
        },
        handleTagsOption (type) {
            if (type.includes('all')) {
                // 关闭所有，除了home
                let res = this.list.filter(item => item.name === this.$config.homeName)
                this.$emit('on-close', res, 'all')
            } else if (type.includes('others')) {
                // 关闭除当前页和home页的其他页
                let res = this.list.filter(item => routeEqual(this.currentRouteObj, item) || item.name === this.$config.homeName)
                this.$emit('on-close', res, 'others', this.currentRouteObj)
                setTimeout(() => {
                    this.getTagElementByName(this.currentRouteObj.name)
                }, 100)
            }
        },
        handleClose (current) {
            if(current.params && current.params.isEdit){
                this.$confirm("设计档案:"+current.params.id+", 确定退出?", '温馨提示',{
                    confirmButtonText: '确定',
                    cancelButtonText: '取消',
                    type: 'warning'
                }).then(() => {
                    if (current.meta && current.meta.beforeCloseName && current.meta.beforeCloseName in beforeClose) {
                        new Promise(beforeClose[current.meta.beforeCloseName]).then(close => {
                            if (close) {
                                this.close(current)
                            }
                        })
                    } else {
                        this.close(current)
                    }
                }).catch(() => {

                });
            }else{
                if (current.meta && current.meta.beforeCloseName && current.meta.beforeCloseName in beforeClose) {
                    new Promise(beforeClose[current.meta.beforeCloseName]).then(close => {
                        if (close) {
                            this.close(current)
                        }
                    })
                } else {
                    this.close(current)
                }
            }
        },
        close (route) {
            let res = this.list.filter(item => !routeEqual(route, item))
            this.$emit('on-close', res, undefined, route)
        },
        handleClick (item) {
            if(this.$route.name == item.name &&
                this.$route.params && item.params && item.params.id == this.$route.params.id){
                return;
            }
            this.$emit('input', item)
        },
        showTitleInside (item) {
            return showTitle(item, this)
        },
        isCurrentTag (item) {
            return routeEqual(this.currentRouteObj, item)
        },
        moveToView (tag) {
            const outerWidth = this.$refs.scrollOuter.offsetWidth
            const bodyWidth = this.$refs.scrollBody.offsetWidth
            if (bodyWidth < outerWidth) {
                this.tagBodyLeft = 0
            } else if (tag.offsetLeft < -this.tagBodyLeft) {
                // 标签在可视区域左侧
                this.tagBodyLeft = -tag.offsetLeft + this.outerPadding
            } else if (tag.offsetLeft > -this.tagBodyLeft && tag.offsetLeft + tag.offsetWidth < -this.tagBodyLeft + outerWidth) {
                // 标签在可视区域
                this.tagBodyLeft = Math.min(0, outerWidth - tag.offsetWidth - tag.offsetLeft - this.outerPadding)
            } else {
                // 标签在可视区域右侧
                this.tagBodyLeft = -(tag.offsetLeft - (outerWidth - this.outerPadding - tag.offsetWidth))
            }
        },
        getTagElementByName (route) {
            this.$nextTick(() => {
                this.refsTag = this.$refs.tagsPageOpened
                this.refsTag.forEach((item, index) => {
                    if (routeEqual(route, item.$attrs['data-route-item'])) {
                        let tag = this.refsTag[index].$el
                        this.moveToView(tag)
                    }
                })
            })
        },
        contextMenu (item, e) {
            if (item.name === this.$config.homeName) {
                return
            }
            this.visible = true
            const offsetLeft = this.$el.getBoundingClientRect().left
            this.contextMenuLeft = e.clientX - offsetLeft + 10
            this.contextMenuTop = e.clientY - 64
        },
        closeMenu () {
            this.visible = false
        }
    },
    mounted () {
        setTimeout(() => {
            this.getTagElementByName(this.$route)
        }, 200)
    }
}
</script>

<style lang="less">
@import './tags-nav.less';
</style>
